package com.lap.framework.common.tool;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;

/**
 * 文件名转换
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
@UtilityClass
public class Named {

  private static final String EMPTY = "";
  private static final String BACKSLASH = "/";
  private static final String PERIOD = ".";
  private static final String UNDERSCORE = "_";
  private static final String HYPHEN = "-";

  // 不规则复数形式映射
  private static final Map<String, String> IRREGULAR_PLURALS = new HashMap<>();

  static {
    IRREGULAR_PLURALS.put("class", "classes");
    IRREGULAR_PLURALS.put("person", "people");
    IRREGULAR_PLURALS.put("child", "children");
    IRREGULAR_PLURALS.put("man", "men");
    IRREGULAR_PLURALS.put("woman", "women");
    IRREGULAR_PLURALS.put("foot", "feet");
    IRREGULAR_PLURALS.put("tooth", "teeth");
    IRREGULAR_PLURALS.put("mouse", "mice");
    IRREGULAR_PLURALS.put("goose", "geese");
    IRREGULAR_PLURALS.put("ox", "oxen");
    IRREGULAR_PLURALS.put("bus", "buses");
  }

  /**
   * 点转换到反斜杠，处理连续点和前后点的情况
   *
   * <ol>
   *   <li>"com.lap..permission" -> "com/lap/permission/"
   *   <li>"com..lap." -> "com/lap/"
   *   <li>".com..lap" -> "com/lap/"
   *   <li>" com.lap..permission " -> "com/lap/permission/"
   * </ol>
   *
   * @param periodsPath 点号路径
   * @return 文件路径
   */
  public static String periods2Path(String periodsPath) {
    if (StringUtils.isBlank(periodsPath)) {
      return EMPTY;
    }

    String trimmed = periodsPath.trim();
    // 处理连续点和前后点
    String[] parts = trimmed.split("\\" + PERIOD);
    String filtered =
        Arrays.stream(parts).filter(StringUtils::isNotBlank).collect(Collectors.joining(BACKSLASH));

    return filtered.isEmpty() ? EMPTY : filtered + BACKSLASH;
  }

  /**
   * 默认使用"_"作为分隔符，转换到大写开头驼峰名字
   *
   * <ol>
   *   <li>"test__person" -> "TestPerson"
   *   <li>" test__person" -> "TestPerson"
   *   <li>" test__person " -> "TestPerson"
   * </ol>
   *
   * @param name 文件名
   * @return 大写驼峰名字
   */
  public static String upperHump(String name) {
    return upperHump(name, UNDERSCORE);
  }

  /**
   * 转换到大写开头的驼峰名字
   *
   * <ol>
   *   <li>"test__person","_" -> "TestPerson"
   *   <li>" test__person","_" -> "TestPerson"
   *   <li>" test__person ","_" -> "TestPerson"
   * </ol>
   *
   * @param name 文件名
   * @param separator 分隔符
   * @return 大写开头驼峰名字
   */
  public static String upperHump(String name, String separator) {
    if (StringUtils.isBlank(name)) {
      return EMPTY;
    }

    if (StringUtils.isBlank(separator)) {
      return capitalizeFirst(name.trim());
    }

    String[] parts = StringUtils.split(name.trim(), separator);
    return Arrays.stream(parts)
        .filter(StringUtils::isNotBlank)
        .map(Named::capitalizeFirst)
        .collect(Collectors.joining());
  }

  /**
   * 默认使用"_"作为分隔符，转换到小写开头驼峰名字
   *
   * <ol>
   *   <li>"test__person" -> "testPerson"
   *   <li>" test__person" -> "testPerson"
   *   <li>" test__person " -> "testPerson"
   * </ol>
   *
   * @param name 文件名
   * @return 小写开头驼峰名字
   */
  public static String lowerHump(String name) {
    return lowerHump(name, UNDERSCORE);
  }

  /**
   * 转换到小写开头驼峰名字
   *
   * <ol>
   *   <li>"test__person","_" -> "testPerson"
   *   <li>" test__person","_" -> "testPerson"
   *   <li>" test__person ","_" -> "testPerson"
   * </ol>
   *
   * @param name 文件名
   * @param separator 分隔符
   * @return 小写开头驼峰名字
   */
  public static String lowerHump(String name, String separator) {
    if (StringUtils.isBlank(name)) {
      return EMPTY;
    }

    String result = upperHump(name, separator);
    if (result.isEmpty()) {
      return EMPTY;
    }

    return result.substring(0, 1).toLowerCase() + result.substring(1);
  }

  /**
   * 获取文件名称，包含扩展名字
   *
   * @param name 文件名
   * @param ext 文件扩展名(".java")
   * @return 文件名称
   */
  public static String fileName(String name, String ext) {
    if (StringUtils.isBlank(name)) {
      return EMPTY;
    }

    return name.trim() + (ext == null ? EMPTY : ext);
  }

  /**
   * 下划线转换到连字符名称
   *
   * @param name 文件名称
   * @return 连字符名称
   */
  public static String mappingUri(String name) {
    if (StringUtils.isBlank(name)) {
      return EMPTY;
    }

    String trimmed = name.trim();
    // 替换下划线为连字符
    String result = trimmed.replace(UNDERSCORE, HYPHEN);

    // 处理复数形式：只对最后一个单词进行复数化
    return pluralizeLastWord(result);
  }

  /**
   * 只对最后一个单词进行复数化
   *
   * @param phrase 短语
   * @return 复数化后的短语
   */
  private static String pluralizeLastWord(String phrase) {
    if (StringUtils.isBlank(phrase)) {
      return phrase;
    }

    // 如果短语中没有连字符，直接对整个短语进行复数化
    if (!phrase.contains(HYPHEN)) {
      return toPlural(phrase);
    }

    // 分割短语，只对最后一个单词进行复数化
    String[] parts = phrase.split(HYPHEN);
    if (parts.length == 0) {
      return phrase;
    }

    // 复数化最后一个单词
    String lastWord = parts[parts.length - 1];
    String pluralLastWord = toPlural(lastWord);

    // 重新组合短语
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < parts.length - 1; i++) {
      result.append(parts[i]).append(HYPHEN);
    }
    result.append(pluralLastWord);

    return result.toString();
  }

  /**
   * 将单词转换为复数形式
   *
   * @param word 输入单词
   * @return 复数形式
   */
  private static String toPlural(String word) {
    if (StringUtils.isBlank(word)) {
      return word;
    }

    // 首先检查不规则复数（最高优先级）
    if (IRREGULAR_PLURALS.containsKey(word)) {
      return IRREGULAR_PLURALS.get(word);
    }

    // 检查是否已经以s结尾
    if (word.endsWith("s")) {
      return word;
    }

    // 检查以y结尾的单词
    if (word.endsWith("y")) {
      char beforeY = word.charAt(word.length() - 2);
      if (!isVowel(beforeY)) {
        return word.substring(0, word.length() - 1) + "ies";
      }
    }

    // 检查以s, x, z, ch, sh结尾的单词
    if (word.endsWith("s")
        || word.endsWith("x")
        || word.endsWith("z")
        || word.endsWith("ch")
        || word.endsWith("sh")) {
      return word + "es";
    }

    // 默认规则：添加s
    return word + "s";
  }

  /**
   * 判断字符是否为元音字母
   *
   * @param c 字符
   * @return 是否为元音
   */
  private static boolean isVowel(char c) {
    return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E'
        || c == 'I' || c == 'O' || c == 'U';
  }

  /**
   * 首字母大写
   *
   * @param str 输入字符串
   * @return 首字母大写的字符串
   */
  private static String capitalizeFirst(String str) {
    if (StringUtils.isBlank(str)) {
      return str;
    }
    return str.substring(0, 1).toUpperCase() + str.substring(1);
  }
}
